using UnityEngine;
using GameFramework;
using UnityGameFramework.Runtime;

namespace LS
{
    public static class VariableUtil
    {
        public static Variable Create<T>(T value)
        {
            Variable variable = null;
            if (value is bool)
            {
                variable = ReferencePool.Acquire<VarBoolean>();
            }
            else if (value is string)
            {
                variable = ReferencePool.Acquire<VarString>();
            }
            else if (value is byte)
            {
                variable = ReferencePool.Acquire<VarByte>();
            }
            else if (value is sbyte)
            {
                variable = ReferencePool.Acquire<VarSByte>();
            }
            else  if (value is byte[])
            {
                variable = ReferencePool.Acquire<VarByteArray>();
            }
            else if (value is char)
            {
                variable = ReferencePool.Acquire<VarChar>();
            }
            else if (value is char[])
            {
                variable = ReferencePool.Acquire<VarCharArray>();
            }
            else if (value is float)
            {
                variable = ReferencePool.Acquire<VarSingle>();
            }
            else if (value is double)
            {
                variable = ReferencePool.Acquire<VarDouble>();
            }
            else if (value is decimal)
            {
                variable = ReferencePool.Acquire<VarDecimal>();
            }
            else if (value is short)
            {
                variable = ReferencePool.Acquire<VarInt16>();
            }
            else if (value is int)
            {
                variable = ReferencePool.Acquire<VarInt32>();
            }
            else if (value is long)
            {
                variable = ReferencePool.Acquire<VarInt64>();
            }
            else if (value is ushort)
            {
                variable = ReferencePool.Acquire<VarUInt16>();
            }
            else if (value is uint)
            {
                variable = ReferencePool.Acquire<VarUInt32>();
            }
            else if (value is ulong)
            {
                variable = ReferencePool.Acquire<VarUInt64>();
            }
            else if (value is System.DateTime)
            {
                variable = ReferencePool.Acquire<VarDateTime>();
            }
            else if (value is Color)
            {
                variable = ReferencePool.Acquire<VarColor>();
            }
            else if (value is Color32)
            {
                variable = ReferencePool.Acquire<VarColor32>();
            }
            else if (value is UnityEngine.Vector2)
            {
                variable = ReferencePool.Acquire<VarVector2>();
            }
            else if (value is UnityEngine.Vector3)
            {
                variable = ReferencePool.Acquire<VarVector3>();
            }
            else if (value is UnityEngine.Vector4)
            {
                variable = ReferencePool.Acquire<VarVector4>();
            }
            else if (value is UnityEngine.Quaternion)
            {
                variable = ReferencePool.Acquire<VarQuaternion>();
            }
            else if (value is UnityEngine.Rect)
            {
                variable = ReferencePool.Acquire<VarRect>();
            }
            else if (value is UnityEngine.Bounds)
            {
                variable = ReferencePool.Acquire<VarBounds>();
            }
            else if (value is UnityEngine.BoundsInt)
            {
                variable = ReferencePool.Acquire<VarBoundsInt>();
            }
            else if (value is System.Numerics.BigInteger)
            {
                variable = ReferencePool.Acquire<VarBigInteger>();
            }

            if (variable != null)
            {
                (variable as Variable<T>).Value = value;
                return variable;
            }
            
            System.Type valueType = value.GetType();
            
            if (valueType.IsArray)
            {
                variable = ReferencePool.Acquire<VarArray<T>>();
            }
            else if (valueType.FullName.StartsWith(typeof(System.Collections.Generic.Dictionary<,>).FullName))
            {
                var dicType = typeof(VarDictionary<,>);
                var genTypes = valueType.GetGenericArguments();
                var newType = dicType.MakeGenericType(genTypes);
                variable = (Variable)ReferencePool.Acquire(newType);
            }
            else if (valueType.FullName.StartsWith(typeof(System.Collections.Generic.List<>).FullName))
            {
                var dicType = typeof(VarList<>);
                var genTypes = valueType.GetGenericArguments();
                var newType = dicType.MakeGenericType(genTypes);
                variable = (Variable)ReferencePool.Acquire(newType);
            }
            else if (value is UnityEngine.GameObject)
            {
                variable = ReferencePool.Acquire<VarGameObject>();
            }
            else if (value is UnityEngine.Transform)
            {
                variable = ReferencePool.Acquire<VarTransform>();
            }
            else if (value is Material)
            {
                variable = ReferencePool.Acquire<VarMaterial>();
            }
            else if (value is UnityEngine.Texture)
            {
                variable = ReferencePool.Acquire<VarTexture>();
            }
            else if (value is UnityEngine.Object)
            {
                variable = ReferencePool.Acquire<VarUnityObject>();
            }
            else
            {
                variable = ReferencePool.Acquire<VarObject>();
            }
            variable.SetValue(value);
            return variable;
        }
    }
}
